import { app, BrowserWindow, ipcMain, Menu, shell, Tray } from 'electron'
import { join } from 'path'
import { electronApp, is, optimizer } from '@electron-toolkit/utils'
import Ipc from './ipc'
import { saveWindow } from './windowProxy'
import ADB from './db/ADB'
import FileUtils from './fileUtils'
import { VUEJS_DEVTOOLS } from 'electron-devtools-installer'

const NODE_ENV = process.env.NODE_ENV

const loginWinWidth = 300
const loginWinHeight = 400

/**
 * 创建主窗口
 *
 * 该函数初始化并配置应用程序的主窗口。它设置了窗口的大小、样式和各种性能选项。
 * 主要目的是为了提供一个适合应用程序运行的环境。
 *
 * @returns {BrowserWindow} 返回创建的主窗口对象
 */
function createWindow() {
  // 创建主窗口实例
  let mainWindow = new BrowserWindow({
    // 设置窗口图标的路径
    icon: join(__dirname, '../../resources/sweetcircle-ico.png'), // 直接使用路径
    // 设置窗口的初始宽度和高度
    width: loginWinWidth,
    height: loginWinHeight,
    // 初始时隐藏窗口，直到完全加载完毕
    show: false,
    // 隐藏菜单栏
    autoHideMenuBar: true,
    // 禁止用户调整窗口大小
    resizable: false,
    // 隐藏窗口标题栏
    titleBarStyle: 'hidden',
    // 启用窗口边框
    frame: false,
    // 配置窗口的JavaScript环境
    transparent: true,
    backgroundColor: '#ffffff',
    webPreferences: {
      // 指定预加载脚本的路径
      preload: join(__dirname, '../preload/index.js'),
      // 禁用沙箱模式
      sandbox: false,
      contextIsolation: false, // 启用上下文隔离
      nodeIntegration: false
    }
  })

  saveWindow('main', mainWindow)

  mainWindow.on('resize', () => {
    const [width, height] = mainWindow.getSize()
    // 发送窗口大小变化事件到渲染进程
    mainWindow.webContents.send('window-resized', {
      width,
      height
    })
  })

  //托盘
  const tray = new Tray(join(__dirname, '../../resources/sweetcircle-ico.png'))
  const contextMenu = [
    {
      label: '退出SweetCircle',
      click: function () {
        app.exit()
      }
    }
  ]
  const menu = Menu.buildFromTemplate(contextMenu)
  tray.setToolTip('SweetCircle')
  tray.setContextMenu(menu)
  // 点击托盘图标，显示主窗口
  tray.on('click', () => {
    mainWindow.setSkipTaskbar(false)
    mainWindow.show()
  })
  /**
   * 处理窗口标题操作的事件监听器。
   * 该函数监听来自渲染进程的 'winTitleOp' 事件，并根据传入的操作类型和数据执行相应的窗口标题操作。
   *
   * @param {Object} e - 事件对象，包含发送事件的相关信息。
   * @param {Object} e.sender - 发送事件的 WebContents 对象。
   * @param {Object} param1 - 包含操作类型和数据的对象。
   * @param {string} param1.action - 要执行的操作类型。
   * @param {any} param1.data - 操作所需的数据。
   */
  ipcMain.on('winTitleOp', (e, { action, data }) => {
    // 获取发送事件的 WebContents 对象
    // const webContents = e.sender

    // 从 WebContents 对象获取对应的 BrowserWindow 对象
    // const win = BrowserWindow.fromWebContents(webContents)
    const win = BrowserWindow.fromWebContents(e.sender)

    // 调用 Ipc.winTitleOp 方法，执行具体的窗口标题操作
    Ipc.winTitleOp(win, action, data)
  })

  /**
   * 切换登录窗口大小
   */
  ipcMain.on('switchWindow', (e, args) => {
    Ipc.switchWindow(mainWindow, args)
  })

  /**
   * 处理登录成功后的操作。
   * 当登录成功时，此回调函数被调用，用于设置主窗口的属性。
   * @param {IpcMainEvent} event - 登录成功后返回的配置对象。
   * @param {Function} config - 登录成功后返回的配置对象。
   * @param {string} args
   */
  ipcMain.on('loginSuccess', (event, args) => {
    Ipc.loginSuccess(event, mainWindow, args)
  })

  /**
   * 打开设置窗口
   */
  ipcMain.on('openSettingWindow', () => {
    Ipc.openWindow({
      windowId: 'setting',
      title: '设置',
      weight: 700,
      height: 500,
      path: '/setting',
      callback: () => {}
    })
  })

  /**
   * 更新用户信息
   */
  ipcMain.on('updateUserInfoA', (event, config) => {
    Ipc.updateUserInfo(config)
  })

  /**
   * 打开文件管理窗口
   */
  ipcMain.on('openFileManageWindow', () => {
    Ipc.openWindow({
      windowId: 'fileManage',
      title: '文件管理',
      weight: 950,
      height: 700,
      path: '/fileManage',
      callback: () => {}
    })
  })
  /**
   * 退出登录
   */
  ipcMain.on('loginOut', () => {
    Ipc.loginOut(mainWindow)
  })

  ipcMain.handle('getExpressPort', () => {
    return Ipc.getExpressPort()
  })

  /**
   * 保存离线消息
   */
  ipcMain.handle('saveOfflineMessages', async (event, data) => {
    return await Ipc.saveOfflineMessages(event, mainWindow, data)
  })
  ipcMain.handle('saveFileMessage', (event, { fileName, messageType, userId, sendUserId, token }) => {
      Ipc.saveFileMessage(fileName, messageType, userId, sendUserId, token)
    }
  )
  /**
   * 加载聊天会话
   */
  ipcMain.handle('getAllChatSession', async () => {
    return await ADB.getChatSessionList()
  })
  /**
   * 添加聊天会话
   */
  ipcMain.handle('addChatSession', async (event, data) => {
    return await ADB.addChatSession(data)
  })

  /**
   * 根据会话ID获取聊天会话
   */
  ipcMain.handle('getAllMessageBySessionId', async (event, sessionId) => {
    return await ADB.getChatMessageList(sessionId)
  })

  /**
   * 添加聊天消息
   */
  ipcMain.handle('addChatMessage', async (event, data, code, extraData) => {
    if (code === 11 && extraData) {
      // 拷贝文件到应用路径
      let filePath = FileUtils.copyFile(extraData)
      if (!filePath) {
        return { status: false, msg: '文件不存在' }
      }
      data.messageContent = filePath
      const res = await ADB.addChatMessage(data) // 保存数据库
      if (res.status) {
        return { status: true, msg: 'OK', data: { filePath: filePath } }
      } else {
        return { status: false, msg: '保存失败' }
      }
    } else {
      const res = await ADB.addChatMessage(data) // 保存数据库
      if (res.status) {
        return { status: true, msg: 'OK' }
      } else {
        return { status: false, msg: '保存失败' }
      }
    }
  })
  ipcMain.handle('deleteChatSession', async (event, data, reloadSession) => {
    const res = await ADB.deleteChatSession(data)
    if (!res.status) {
      return res
    }
    const ress = await ADB.deleteChatMessage(data)
    if (!ress.status) {
      return ress
    }
    if (reloadSession) {
      const r = await ADB.getChatSessionList()
      event.sender.send('reloadSession', r)
    }

    return { status: true, msg: 'OK' }
  })

  //打开控制台
  if (NODE_ENV === 'development') {
    mainWindow.webContents.openDevTools()
  }

  // 窗口加载完成后显示窗口
  mainWindow.on('ready-to-show', () => {
    mainWindow.show()
    mainWindow.setTitle('SweetCircle')
  })

  // 阻止默认的窗口打开行为
  mainWindow.webContents.setWindowOpenHandler((details) => {
    shell.openExternal(details.url).then()
    return { action: 'deny' }
  })

  // 基于 electron-vite cli 的渲染器的 HMR。
  //   加载用于开发的远程 URL 或用于生产的本地 html 文件。
  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']).then()
  } else {
    mainWindow.loadFile(join(__dirname, '../renderer/index.html')).then()
  }
}

// 当 Electron 完成时，将调用此方法
// 初始化并准备好创建浏览器窗口。
// 某些 API 只能在此事件发生后使用。
app.whenReady().then(() => {
  // 设置 Windows 的应用程序用户模型 ID
  electronApp.setAppUserModelId('com.electron')

  // 开发中默认按F12打开或关闭DevTools
  // 并在生产中忽略 CommandOrControl + R。
  // 见 https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
  app.on('browser-window-created', (_, window) => {
    optimizer.watchWindowShortcuts(window)
  })

  createWindow()

  app.on('activate', function () {
    // 在 macOS 上，当单击停靠图标并且没有打开其他窗口时，通常会在应用程序中重新创建一个窗口。
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })

  if (process.env.NODE_ENV === 'development') {
    const { default: installExtension, VUEJS_DEVTOOLS } = require('electron-devtools-installer')
    // 安装 Vue DevTools
    installExtension(VUEJS_DEVTOOLS)
      .then((name) => console.log(`Added Extension:  ${name.name}`))
      .catch((err) => console.log('An error occurred: ', err))
  }
})

// 当所有窗口关闭时退出（macOS 除外）。在那里，应用程序及其菜单栏通常会保持活动状态，直到用户使用 Cmd + Q 显式退出。
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    console.log('app.quit')
    app.quit()
  }
})

// 在此文件中，您可以包含应用程序特定主流程代码的其余部分。您也可以将它们放在单独的文件中并在此处引用它们。
